package com.distributed.tcp.server;

import com.distributed.tcp.manager.DeviceConnectionManager;
import com.distributed.tcp.manager.MessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
public class NettyServer {
    private final int port;
    private final MessageHandler messageHandler;
    private final ExecutorService executor;
    private final DeviceConnectionManager connectionManager;
    private Channel serverChannel;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    public NettyServer(int port, MessageHandler messageHandler, 
                      ExecutorService executor, DeviceConnectionManager connectionManager) {
        this.port = port;
        this.messageHandler = messageHandler;
        this.executor = executor;
        this.connectionManager = connectionManager;
    }

    /**
     * 启动服务器
     */
    public void start() throws InterruptedException {
        // 从配置获取线程数，默认1和CPU核心数*2
        bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
        workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors()*2);

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .option(ChannelOption.SO_TIMEOUT, 3000) // 添加超时配置
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.TCP_NODELAY, true) // 禁用Nagle算法，减少延迟
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());
                            // 只检测读空闲（客户端超过10分钟秒未发送任何数据则判定为离线）
                            // 取消写空闲检测（不再需要服务器主动发心跳）
                            pipeline.addLast(new IdleStateHandler(60*5, 0, 0, TimeUnit.SECONDS));
                            pipeline.addLast(new TcpServerHandler(
                                    port, connectionManager, messageHandler, executor
                            ));
                        }
                    });
            ChannelFuture future = bootstrap.bind(port).sync();
            log.info("TCP服务器已启动，端口: {}", port);
            serverChannel = future.channel();

            // 添加关闭监听器，处理异常关闭
            serverChannel.closeFuture().addListener(f -> {
                if (!f.isSuccess()) {
                    log.error("服务器端口{}异常关闭", port, f.cause());
                }
            }).sync();
        } finally {
            workerGroup.shutdownGracefully(1, 5, TimeUnit.SECONDS); // 优雅关闭参数
            bossGroup.shutdownGracefully(1, 5, TimeUnit.SECONDS);
            log.info("TCP服务器已停止，端口: {}", port);
        }
    }

    /**
     * 停止服务器
     */
    public void stop() {
        if (serverChannel != null) {
            serverChannel.close();
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
    }

    public int getPort() {
        return port;
    }
}
